package cn.edu.wynu.d2_polymorphism;
/*
使用多态的好处：
在多态形式下，右边对象是解耦合的，更便于扩展和维护。
定义方法时，使用父类类型的形参，可以接收一切子类对象，扩展性更强、更便利。
*/

/*
类型转换：
自动类型转换:父类 变量名=new子类();      例如：People p=new Teacher();
强制类型转换:子类 变量名=(子类)父类变量   例如：Teacher t=(Teacher)p;

强制类型转换的一个注意事项：
存在继承/实现关系就可以在编译阶段进行强制类型转换，编译阶段不会报错。
运行时，如果发现对象的真实类型与强转后的类型不同，就会报类型转换异常(ClassCastException)的错误出来。
People p = new Teacher();
Student s = (student) p; // java.lang.ClassCastException

强转前，Java建议：使用instanceof关键字，判断当前对象的真实类型，再进行强转。
语法格式：对象 instanceof 类名
例：p instanceof Student
*/

public class Test {
    public static void main(String[] args) {
        // 理解多态的好处
        // 1、可以实现解耦合，右边对象可以随时切换，后续业务随机改变
        // 换句话说就是，如果子类Student不好用了，可以直接切换为Teacher，这就不用修改其他代码。
        People p1 = new Student();
        p1.run();

        // 3、多态下会产生的一个问题，怎么解决?多态下不能使用子类的独有功能。
        // p1.test(); // 报错，多态下存在的问题，无法直接调用子类的独有功能

        // 4、要解决这个不能使用子类的独有功能的问题，可以使用强制类型转换
        Student s1 = (Student) p1; // 强制类型转换，将p1转换为Student对象
        s1.test(); // 这样就可以使用子类的独有功能

        // 5、强制类型转换可能存在的问题:编译阶段有继续或者实现关系就可以强制转换，但是运行时可能出现类型转换异常
        // 此时代码所表达的意识就是：编译的时候，p1指向的是一个学生对象，但运行时发现p1指向的是Teacher对象，所以强制转换失败
        // 不建议 Teacher t1 = (Teacher) p1; // 虽然这会儿编译没有问题，但运行时可能出现类型转换异常

        // 6、解决强制类型转换可能存在的问题，可以使用instanceof关键字判断当前对象的真实类型
        if (p1 instanceof Student) {
            Student s2 = (Student) p1; // 强制类型转换，将p1转换为Student对象
            s2.test(); // 这样就可以使用子类的独有功能
        }else if (p1 instanceof Teacher) {
            Teacher t2 = (Teacher) p1; // 强制类型转换，将p1转换为Teacher对象
            t2.teach(); // 这样就可以使用子类的独有功能
        }

        System.out.println("-----------------------------");

        // 2、可以使用父类类型的变量作为形参，可以接收一切子类对象
        Student s = new Student();
        go(s);

        Teacher t = new Teacher();
        go(t);
    }
    // 可以使用父类类型的变量作为形参，可以接收一切子类对象
    /*
    public static void go(Student s) { // 这里就只能接收Student对象，Teacher对象不能接收
    }*/
    public static void go(People p) { // 这里可以接收一切子类对象
        p.run(); // 可以调用通用功能，它的每个方法都重写了
        if (p instanceof Student) { // 独有功能就必须加判断
            Student s = (Student) p;
            s.test();
        }else if (p instanceof Teacher) {
            Teacher t = (Teacher) p;
            t.teach();
        }
    }
}
/*
1、类型转换有几种形式?能解决什么问题?
自动类型转换、强制类型转换。
可以把对象转换成其真正的类型，从而解决了多态下不能调用子类独有方法的问题。
2、强制类型转换需要注意什么?
存在继承/实现时，就可以进行强制类型转换，编译阶段不会报错。
但是，运行时，如果发现对象的真实类型与强转后的类型不同会报错(ClassCastException)。
3、强制类型转换前?Java建议我们做什么事情?
instanceof判断当前对象的真实类型:对象instanceof类型
*/



